import Arc, { ArcProps } from "src/shape/Arc"
import Arrow, { ArrowProps } from "src/shape/Arrow"
import BoxSelectFrame from "src/shape/BoxSelectFrame"
import Erase from "src/shape/Erase"
import Group, { GroupProps } from "src/shape/Group"
import Pen from "src/shape/pen"
import Pentagram, { PentagramProps } from "src/shape/Pentagram"
import Rect, { RectProps } from "src/shape/Rect"
import Scene, { Option } from "src/shape/Scene"
// import TableFrame from "src/shape/TableFrame"
import Textarea from "src/shape/Textarea"
import Triangle, { TriangleProps } from "src/shape/Triangle"
// import videoFrame from "src/shape/VideoFrame"
import { darwModel,shapeType } from "src/types/drawBoard"
import { Props, Shape } from "src/types/shape"
import utils from "src/utils"
import Stack from "src/utils/Stack"
// import TWEEN, { Tween } from "@tweenjs/tween.js"
// 撤销恢复，橡皮擦，插入文字
// 画板类
export default class extends Scene {
    history = new Stack<{name: string, data: Props[]}>()
    model: darwModel = 'normal'
    erase: Erase
    pen: Pen
    textarea: Textarea
    boxSelect: BoxSelectFrame
    private scale: number = 1 //缩放倍速
    public ratio: number = 0.5  //每次缩放
    private offsetx: number = 0 //缩放X轴
    private offsety: number = 0//缩放Y轴
    private rollerEventfn: any
    constructor(canvas: HTMLCanvasElement,option?: Option) {
        if(!canvas || !(canvas instanceof Element)) throw new Error('The incoming type is incorrect, please pass in the "Element" type')
        super(canvas, option)
        this.erase = new Erase(this)
        this.pen = new Pen(this)
        this.textarea = new Textarea(this)
        this.boxSelect = new BoxSelectFrame(this)
        this.rollerEventfn = this.rollerEvent.bind(this)
        this.initRollerEvent()

        this.boxSelect.open()
        // const table = new TableFrame(new Props(),this)

        // this.add(table)
        // new Tween(table.props).to({lateX: 500,lateY: 200},3000).onUpdate((obj,ela)=>{
        //     console.log(obj.lateX);
        // }).start()
        this.animate()
        this.closeRollerEvent()
    }
    import(options: any) {
        this.width = options.width
        this.height = options.height
        this.updateCanvasInfo()

        const deep = (shapes: Shape[], group: Scene | Group)=>{
            shapes.forEach((shape: Shape) => {
                switch (shape.type) {
                    case shapeType.arc:
                        group.add(new Arc(shape.props))
                        break
                    case shapeType.arrow:
                        group.add(new Arrow(shape.props))
                        break
                    case shapeType.pentagram:
                        group.add(new Pentagram(shape.props))
                        break
                    case shapeType.rect:
                        group.add(new Rect(shape.props))
                        break
                    case shapeType.triangle:
                        group.add(new Triangle(shape.props))
                        break
                    case shapeType.group:
                        const _group = new Group(shape.props)
                        _group.removeAll()
                        
                        group.add(_group)
                        deep(shape.props.shapes,_group)
                        break
                }
            })
        }
        deep(options.shapes, this)

        this.setHistory()
        this.render()
    }
    export() {
        const json = {
            width: this.width,
            height: this.height,
            shapes: this.shapes.map(item=>{
                return {
                    type: item.type,
                    props: item.props
                }
            })
        }
        console.log(json);
        console.log(JSON.stringify(json));

        return JSON.stringify(json)
    }
    animate() {
        // TWEEN.update()
        this.render()
        window.requestAnimationFrame(this.animate.bind(this))
    }
    setModel(type: darwModel) {
        this.model = type
        switch (type) {
            case 'erase':
                this.erase.open()
                this.pen.close()
                this.shapesEvent.close()
                this.textarea.close()
                this.boxSelect.close()
                break
            case 'pen':
                this.pen.open()
                this.erase.close()
                this.shapesEvent.close()
                this.textarea.close()
                this.boxSelect.close()
                break
            case 'textarea':
                this.textarea.open()
                this.pen.close()
                this.erase.close()
                this.shapesEvent.close()
                this.boxSelect.close()
                break
            case 'normal':
                this.shapesEvent.open()
                this.boxSelect.open()
                this.erase.close()
                this.pen.close()
                this.textarea.close()
        }
    }
    setHistory() {
        const shapes = this.shapes.map(shape => utils.object.Copy(shape.props))        
        this.history.push({ name: 'shapes', data: shapes })
    }
    setShapes() {
        this.shapes.forEach(shape => {
            this.history.getCurrent()?.data.forEach((item: any) => {
                if (shape.getRgbaId() == item.id) {
                    shape.setProps(item)
                }
            })
        })
        this.historyID = this.history.getCurrent()?.data.map((item: any) => item.id || item.name) || []        
    }
    // 撤销
    revokeCanvas() {
        this.history.back()
        this.setShapes()
        this.render()
    }
    // 恢复
    recoverCanvas() {
        this.history.go()
        this.setShapes()
        this.render()
    }
    // 重置画布
    resetCanvas() {
        this.history.clear()
        this.clearCanvas()
    }
    /**
     * 放大
     * @param x transformOrigin坐标偏移X轴
     * @param y transformOrigin坐标偏移Y轴
     * @param left 元素left位置
     * @param top 元素top位置
     * @returns 
     */
    amplify(x?: number, y?: number, left?: number, top?: number): void {
        if (this.scale >= 5) return
        const domElement = this.domElement
        const { width, height } = this
        if (!(x && y)) {
            x = width / 2
            y = height / 2
        }
        this.scale += this.ratio
        domElement.style.transform = `scale(${this.scale})`
        domElement.style.transformOrigin = `${x}px ${y}px`
        if (left && top) {
            domElement.style.position = 'absolute'
            domElement.style.top = `${top}px`
            domElement.style.left = `${left}px`
        }
    }
    /**
    * 缩小
    * @param x transformOrigin坐标偏移X轴
    * @param y transformOrigin坐标偏移Y轴
    * @param left 元素left位置
    * @param top 元素top位置
    * @returns 
    */
    reduce(x?: number, y?: number, left?: number, top?: number): void {
        if (this.scale <= 0.2) return
        const domElement = this.domElement
        const { width, height } = this
        if (!(x && y)) {
            x = width / 2
            y = height / 2

        }

        this.scale = this.scale - this.ratio < 0.2 ? 0.2 : this.scale - this.ratio
        domElement.style.transform = `scale(${this.scale})`
        domElement.style.transformOrigin = `${x}px ${y}px`
        if (left && top) {
            domElement.style.position = 'absolute'
            domElement.style.top = `${top}px`
            domElement.style.left = `${left}px`
        }
    }
    /**
     * 移动
     * @param meth 移动的方式 top/bottom/left/right
     * @param count 移动的值
     */
    moveCanvas(meth: string, count: number): void {
        const domElement = this.domElement
        switch (meth) {
            case 'top':
                this.offsety -= count
                break;
            case 'bottom':
                this.offsety += count
                break;
            case 'left':
                this.offsetx -= count
                break;
            case 'right':
                this.offsetx += count
                break;

        }
        domElement.style.transform = `translate(${this.offsetx}px,${this.offsety}px)`
    }
    /**
     * 初始化滚轮事件
     */
    initRollerEvent(): void {
        const domElement = this.domElement
        domElement.addEventListener('wheel', this.rollerEventfn)
    }
    /**
     * canvas滚轮事件执行函数
     * @param e :WheelEvent
     */
    rollerEvent(e: WheelEvent): void {

        e.preventDefault()
        let left = e.clientX - e.offsetX
        let top = e.clientY - e.offsetY
        //小于0向上滚动
        if (e.deltaY < 0) {
            this.amplify(e.offsetX, e.offsetY, left, top)
        } else {
            this.reduce(e.offsetX, e.offsetY, left, top)
        }
    }
    /**
     * 解绑canvas默认滚轮事件
     */
    closeRollerEvent(): void {
        const domElement = this.domElement
        domElement.removeEventListener('wheel', this.rollerEventfn)
    }
    // 画长方形
    Rect(option: RectProps) {
        const rect = new Rect(option)
        this.add(rect)
        this.render()
        this.setHistory()
        return rect
    }
    // 画三角形
    Triangle(option: TriangleProps) {
        const triangle = new Triangle(option)
        this.add(triangle)
        this.render()
        this.setHistory()
        return triangle
    }
    // 画箭头
    Arrow(option: ArrowProps) {
        const arrow = new Arrow(option)
        this.add(arrow)
        this.render()
        this.setHistory()
        return arrow
    }
    // 画圆
    Arc(option: ArcProps) {
        const arrow = new Arc(option)
        this.add(arrow)
        this.render()
        this.setHistory()
        return arrow
    }
    // 画五角星
    Pentagram(option: PentagramProps) {
        const arrow = new Pentagram(option)
        this.add(arrow)
        this.render()
        this.setHistory()
        return arrow
    }
    // 分组
    Group(option: GroupProps) {
        const group = new Group(option)
        this.add(group)
        this.render()
        return group
    }
    setCanvasCursor(url: string): void {
        const domElement = this.domElement
        domElement.style.cursor = `url('../${url}'),auto`
    }
}